﻿namespace PowerSong.Import
    {
    using System;
    using System.Collections.Generic;
    using System.IO;
    using PowerSong.UserInterface;
    using Legacy = PowerSong.SongDatabase.Legacy;
    using Modern = PowerSong.SongDatabase;

    public class LegacyDatabaseImport : BaseImport
        {

        private string sourceLocation = null;

        public LegacyDatabaseImport(Modern.Database destinationDatabase, string sourceLocation)
            : base(destinationDatabase)
            {
            this.sourceLocation = sourceLocation;
            }

        protected override void Import(Modern.Category category, List<string> messages)
            {

            // Create a temporary directory
            var tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            Directory.CreateDirectory(tempDir);
            try
                {

                // Copy all files in the source database to a temporary location (legacy data model may upgrade the database automatically!)
                SetProgress(0, "Creating temporary copy...");
                CopyFiles(tempDir);

                // Open the database at the new location
                SetProgress(10, "Loading database...");
                var source = PowerSong.SongDatabase.Legacy.Database.Load(tempDir);

                // Convert settings
                SetProgress(20, "Converting settings...");
                ConvertSettings(messages, source);

                // Check for plugins, which cannot be converted
                SetProgress(30, "Converting plugins...");
                ConvertPlugins(messages, source);

                // Add styles to the target database
                SetProgress(40, "Converting styles...");
                ConvertStyles(messages, source);

                // Add licenses to the target database
                SetProgress(50, "Converting licenses...");
                ConvertLicenses(messages, source);

                // Add categories to the target database
                SetProgress(60, "Converting categories...");
                ConvertCategories(messages, source);

                // Add songs to the target database
                SetProgress(70, "Converting songs...");
                ConvertSongs(messages, category, source);

                // Add old activity to the target database
                SetProgress(80, "Converting activity...");
                ConvertActivity(messages, source);

                // Try to set the default style if one hasn't already been set
                var settings = new Settings(Destination);
                if (settings.DefaultStyle == null && source.Styles.GetAllStyleNames().Contains("Default"))
                    {
                    settings.DefaultStyle = Destination.Styles.Get("Default");
                    }

                // Compact the target database
                SetProgress(90, "Saving new database...");
                Destination.Compact();
                SetProgress(100, "Done!");

                }
            finally
                {
                Directory.Delete(tempDir, true);
                }

            }

        private void ConvertSettings(List<string> messages, Legacy.Database source)
            {

            // Translate settings (the easy ones)
            var settings = new Settings(Destination);
            settings.AutoCreateProjectionWindow = source.Settings.ShowMainProjection;
            settings.EnableReporting = source.Settings.EnableLogging;
            settings.PopupSongPreviews = source.Settings.ShowSongPreviews;
            settings.NoticeBackgroundColour = (uint)source.Settings.NoticeDefaultBackgroundColour.ToArgb();
            settings.NoticeDuration = source.Settings.NoticeDefaultDuration;
            settings.NoticeTextColour = (uint)source.Settings.NoticeDefaultFontColour.ToArgb();
            settings.NoticeFontName = source.Settings.NoticeFontName;
            settings.NoticeFontSize = source.Settings.NoticeFontSize;
            settings.NoticeFontStyle = LegacyConverter.ConvertFontStyle(source.Settings.NoticeFontStyle);
            settings.NoticeSpeed = source.Settings.NoticeSpeed;
            settings.NoticeTimeToAppear = source.Settings.NoticeTimeIn;
            settings.NoticeTimeToDissappear = source.Settings.NoticeTimeOut;

            // Write messages for settings that cannot be converted
            if (source.Settings.ShowPreviewProjection == false)
                {
                messages.Add("The 'show preview projection' setting was disabled in the legacy database. This version of PowerSong does not support that setting, because preview projections are always displayed.");
                }

            // Try to set the default Bible translation
            var newTranslationName = source.Settings.ActiveBible;
            if (newTranslationName == "BBE") newTranslationName = "Bible in Basic English";
            if (newTranslationName == "KJV") newTranslationName = "King James Version";
            if (BibleTranslationManager.IsTranslationInstalled(newTranslationName))
                {
                settings.ActiveBibleTranslation = newTranslationName;
                }
            else
                {
                messages.Add("The active Bible translation in the legacy database is the '" + source.Settings.ActiveBible + "' translation, but this translation has not been installed for this version of PowerSong. Therefore, no changes will be made to the currently active Bible translation.");
                }

            // Save the changes to the settings
            settings.SaveChanges();

            }

        private void CopyFiles(string tempDir)
            {
            foreach (var originalFile in Directory.GetFiles(sourceLocation))
                {
                var newFile = Path.Combine(tempDir, Path.GetFileName(originalFile));
                File.Copy(originalFile, newFile);
                }
            }

        private static void ConvertPlugins(List<string> messages, Legacy.Database source)
            {
            if (source.PluginFiles.Length > 0)
                {
                messages.Add("The source database contained plugins, which are no longer supported, therefore the plugins were not imported.");
                }
            }

        private void ConvertStyles(List<string> messages, Legacy.Database source)
            {

            // Convert all of the available styles
            foreach (var oldStyle in source.Styles.GetAllStyles())
                {
                try
                    {

                    // Convert the style and save it
                    var newStyle = LegacyConverter.ConvertStyle(oldStyle);
                    Destination.Styles.Write(newStyle);

                    }
                catch (Exception ex)
                    {
                    messages.Add("The style '" + oldStyle.Name + "' could not be converted: " + ex.Message);
                    }
                }
           
            }

        private void ConvertLicenses(List<string> messages, Legacy.Database source)
            {
            foreach (var oldLicense in source.Licenses.GetAllLicenses())
                {
                try
                    {
                    var newLicense = LegacyConverter.ConvertLicense(oldLicense);
                    Destination.Licenses.Write(newLicense);
                    }
                catch (Exception ex)
                    {
                    messages.Add("The license '" + oldLicense.Name + "' could not be converted: " + ex.Message);
                    }
                }
            }

        private void ConvertCategories(List<string> messages, Legacy.Database source)
            {
            foreach (var oldCategory in source.Categories.GetAllCategories())
                {
                try
                    {
                    var newCategory = new Modern.Category();
                    newCategory.ID = oldCategory.Key;
                    newCategory.Name = oldCategory.Value;
                    Destination.Categories.Write(newCategory);
                    }
                catch (Exception ex)
                    {
                    messages.Add("The category '" + oldCategory.Key + "' could not be converted: " + ex.Message);
                    }
                }
            }

        private void ConvertSongs(List<string> messages, Modern.Category category, Legacy.Database source)
            {
            foreach (var songID in source.Songs.GetAllSongIDs())
                {
                try
                    {

                    // Get old song and transform it into new song
                    var oldSong = source.Songs.GetSong(songID);
                    var newSong = LegacyConverter.ConvertSong(oldSong);

                    // Add categories
                    foreach (var categoryID in oldSong.Categories)
                        {
                        var relatedCategory = Destination.Categories.Get(categoryID);
                        newSong.Categories.Add(relatedCategory);
                        if (category != null) newSong.Categories.Add(category);
                        }

                    // Write the new song
                    Destination.Songs.Write(newSong);

                    }
                catch (Exception ex)
                    {
                    messages.Add("The song identified by ID '" + songID.ToString() + "' could not be converted: " + ex.Message);
                    }
                }
            }

        private void ConvertActivity(List<string> messages, Legacy.Database source)
            {

            try
                {

                // Convert all activity log messages
                for (var year = 2000; year < 2100; year++)
                    {
                    for (var month = 0; month <= 12; month++)
                        {
                        if (source.Logging.LogFileExists(year, month))
                            {
                            var recordCount = source.Logging.RecordCount(year, month);
                            for (var recordIndex = 0; recordIndex < recordCount; recordIndex++)
                                {
                                var oldEntry = source.Logging.GetRecord(year, month, recordIndex);
                                if (oldEntry.ItemSort == SongDatabase.Legacy.Logging.LogEntry.ItemType.Song)
                                    {
                                    if (oldEntry.ActionPerformed == SongDatabase.Legacy.Logging.LogEntry.Action.Hidden)
                                        {
                                        Destination.ActivityLog.Write(Modern.ActivityItemType.Song, oldEntry.ItemID, Modern.ActivityAction.Hidden, oldEntry.Time);
                                        }
                                    else if (oldEntry.ActionPerformed == SongDatabase.Legacy.Logging.LogEntry.Action.Shown)
                                        {
                                        Destination.ActivityLog.Write(Modern.ActivityItemType.Song, oldEntry.ItemID, Modern.ActivityAction.Shown, oldEntry.Time);
                                        }
                                    }
                                }
                            }
                        }
                    }

                // Close all the file handles that were opened
                source.Logging.CloseAllFileHandles();

                }
            catch (Exception ex)
                {
                messages.Add("The activity log could not be converted: " + ex.Message);
                }

            }

        }

    }
